let userDao = require('../dao/userDao');
let coinUpdateLogDao = require('../dao/CoinUpdateLogDao');
let logCoinNumDao = require('../dao/LogCoinChangeDao');
let tokenUtil = require('../token');
let timeUtil = require('../util/timeUtil');
let smsService = require('./SmsService');
let redis = require('../dao/redis');
let iconst = require('../iconst');
let tokenService = require('./TokenService');
let cmService = require('./cmService');
let mysqlPool = require('../dao/MySQLPool');
let apollo = require('../config/apollo');
let bcryptUtil = require('../util/bcryptUtil');
let sysUserDao = require('../dao/sysUserDao');
let userLoginRecordDao = require('../dao/userLoginRecordDao');
let clubMemberDao = require('../dao/ClubMemberDao');
let clubCoinsUpdateRecordDao = require('../dao/ClubCoinsUpdateRecordDao');
let winLostRecordDao = require('../dao/WinLostRecordDao');
let wxUtil = require('../util/wxUtil');
let Token = require('../token');

let wxService = require('../service/wxService')

const redisConst = require('../const/redisConst');

const { BusiError, SysError } = require('../exception/exception');

class UserService{
    constructor(){}

    /**
     * 查找用户列表
     * @param cond
     *      {String} cond.uid
     *      {String} cond.name
     *      {String} cond.phone
     *      {String} cond.startTime
     *      {String} cond.endTime
     * @returns {Promise<*>}
     */
    async queryPage(cond){
        let cnt = await userDao.queryPageCntByCond(cond);
        if (cnt <= 0){
            return {cnt: 0, data: []};
        }
        let data = await userDao.queryPageByCond(cond);
        return {cnt: cnt, data: data};
    }

    /**
     * 修改用户头像
     * @param {String} uid
     * @param {String} headimgurl
     * @returns {Promise<void>}
     */
    async modifyAvatar(uid, headimgurl){
        let user = {uid: uid};
        let result = await userDao.getUserByCondition(user);
        if(result.length === 0){
            throw new BusiError(500, "用户不存在");
        }
        user = result[0];
        if(user.account.startsWith("wx_")){
            throw new BusiError(500, "微信用户不支持该功能");
        }
        let affected = await userDao.updateAvatar(uid, headimgurl);
        if (affected < 1){
            throw new BusiError(500, "修改头像失败");
        }
    }

    /**
     * 修改用户微信二维码
     * @param {String} uid
     * @param {String} qrcode
     * @returns {Promise<void>}
     */
    async modifyQrcode(uid, qrcode){
        let affected = await userDao.updateQrcode(uid, qrcode);
        if (affected < 1){
            throw new BusiError(500, "修改二维码失败");
        }
    }

    /**
     * 
     * @param {String} uid 
     * @param {Number} buffer 
     * @param {String} operator 
     * @param {Number} flag 
     */
    async updateBuffer(uid, buffer, operator, flag){
        let lockKey = redisConst.USER_BUFFER_LOCK_KEY + ":" + uid;
        let isLock = await redis.lock(lockKey, "1", 5);
        if(!isLock){
            throw new BusiError(500, "操作太频繁, 请稍后再试");
        }
        
        let user = await userDao.getUserByUid(uid);
        if (!user){
            throw new BusiError(500, "用户不存在");
        }

        let res = await userDao.updateBuffer(uid, operator, buffer);
        if(res <= 0){
            throw new BusiError(500, "操作失败, 请稍后再试");
        }

        if(flag === 1){
            console.logw("update user flag:", uid, buffer, operator);
            await userDao.updateFlag(uid, operator, 11);
        }

        console.logw("update user buffer success:", uid, buffer, operator);
    }

    async updateFlag(uid, flag, operator){        
        let user = await userDao.getUserByUid(uid);
        if (!user){
            throw new BusiError(500, "用户不存在");
        }

        let res = await userDao.updateFlag(uid, operator, flag);
        if(res <= 0){
            throw new BusiError(500, "操作失败, 请稍后再试");
        }

        console.logw("update user flag success:", uid, flag, operator);
    }

    /**
     * 根据旧密码修改密码
     * @param {String} uid
     * @param {String} prePwd
     * @param {String} newPwd
     * @returns {Promise<void>}
     */
    async modifyPwd(uid, prePwd, newPwd){
        //let psw = bcryptUtil.hash(prePwd);
        let userInfo = await userDao.getUserByUid(uid);
        if (!userInfo) {
            throw new BusiError(500, "invalid user");
        }

        if (!bcryptUtil.verify(prePwd, userInfo.password)) {
            throw new BusiError(500, "原密码不正确");
        }

        console.logw("旧密码", prePwd, "更新为新密码", newPwd);
        let newPwdEncode = bcryptUtil.hash(newPwd);
        await userDao.updateUserPassword(uid, newPwdEncode);
    }

    /**
     * 通过验证码修改密码
     * @param {String} mobile
     * @param {String} pwd
     * @param {String} code
     * @returns {Promise<void>}
     */
    async modifyPwdByCode (mobile, pwd, code) {
        let userInfo = await userDao.getUserByMobile(mobile);
        if (!userInfo) {
            throw new BusiError(500, "该用户不存在");
        }

        await smsService.validPwdCode(mobile, code);
        //console.logw(userInfo.uid, "更新为新密码", pwd);
        let newPwdEncode = bcryptUtil.hash(pwd);
        //let newPwdEncode = tokenUtil.aesEncodeDef(pwd);
        await userDao.updateUserPassword(userInfo.uid, newPwdEncode);
    }

    /**
     * 
     * @param {String} uid 
     */
    async autoIncrCoins(uid){
        let user = await userDao.getUserByUid(uid);
        if (user == null) {
            console.logw("用户不存在:", uid);
            return false;
        }

        if (user.coinNum < 1000){
            await userDao.incCoin(uid, 10000);
            return true;
        }

        return false;
    }

    /**
     * 通过账号密码登录
     * @param {String} acct
     * @param {String} pwd
     * @param {String} ip
     * @param {String} ua
     * @param {String} ch
     * @returns {Promise<*>}
     */
    async loginByPwd(acct, pwd, ip, ua, ch){
        let user = await userDao.getUserByMobile(acct);
        if (user == null) {
            console.logw("用户不存在:", acct);
            throw new BusiError(500, "账号或密码错误");
        }

        let is = await this.autoIncrCoins(user.uid);
        if (is){
            user = await userDao.getUserByMobile(acct);
        }

        let res = bcryptUtil.verify(pwd, user.password);
        if (!res){
            console.logw("密码错误:", acct);
            throw new BusiError(500, "账号或密码错误");
        }

        // token刷新
        let token = await tokenService.updateToken(user.uid);

        userLoginRecordDao.save(user.uid, ip, ua, ch);

        user.token = token;
        user.stoken = tokenUtil.aesEncodeDef(ip);
        delete user.password;
        return user;
    }

    async userLoginWithPsw(phone, password, ip){
        return await userDao.userLoginWithPsw(phone, password, ip);
    }

    async addUserByMobile(mobile, nickName, psw, ip, headimgurl){
        return await userDao.addUserByMobile(mobile, nickName, psw, ip, headimgurl);
    }

    async createUserWithPhone(phone, nickname, headimgurl, ip, psw, code, sex){
        return await userDao.createUserWithPhone(phone, nickname, headimgurl, ip, psw, code, sex);
    }

    async getUserByIdAsync(uid){
        return await userDao.getUserByIdAsync(uid);
    }

    async addCoinSafeAsync(uid, addCoin,gameType){
        return await userDao.addCoinSafeAsync(uid, addCoin,gameType);
    }

    async getUserByAccount(account){
        return await userDao.getUserByAccount(account);
    }

    async updateOpenidByUnionid(unionid, openid){
        return await userDao.updateOpenidByUnionid(unionid, openid);
    }

    async handleWxUserInfo(access_token,openid,ip,stoken,unionid) {
        let result = await wxUtil.getUserInfoByAccessToken(access_token,openid);
        if(result.errocode > 0) {
            return result;
        }
        if(typeof result === "string")
            result === JSON.parse(result);
        openid = result.openid;
        if(openid === undefined ) {
            console.logw('get user info from weixin failed .');
            return {code:500,errmsg:"get user info from weixin failed ."};
        }
        let nickname = result.nickname;
        let sex = result.sex;
        let headimgurl = result.headimgurl;
        let account = "wx_" + openid;
        let item={openid:openid,nickname:nickname,sex:sex,headimgurl:headimgurl};
        let wxNickName=Token.base64encode(encodeURIComponent(nickname));
        let ret = {
            code:200,
            errmsg:"ok",
            account:account,
            headimgurl:headimgurl,
            name:nickname,
            wxNickName:wxNickName,
            sex:sex,
            openid:openid,
            cardNum:0,
            unionid:unionid,
        };
        let resData= await this.saveWxUserInfo(account,nickname,headimgurl,sex,ip,wxNickName,unionid);

        //判断账号是否被封
        if(resData.suc === true) {
            console.logw('wechat_auth uid ',resData.uid);
            let resAccess = await userDao.getOrCreateUserAccessAsync(resData.uid,nickname);
            if(resAccess && resAccess.ban_level > 0) {
                let info=nickname+' 此号'+resData.uid+'已被封';
                console.logw(info,'ip',ip);
                item.ban=resAccess.ban_level;
                await wxService.cacheLoginInfo(resData.uid,resData);
                return {code:500,errmsg:info};
            }
            let token=Token.aesEncodeDef(''+resData.uid);//加密用户id
            ret.uid=resData.uid;
            ret.isAgent=resData.isAgent;
            ret.inviteId=resData.inviteId;
            ret.cardNum=resData.cardNum;
            ret.phone=resData.phone;
            ret.phoneCode=resData.phoneCode;
            ret.codeNocheck=resData.codeNocheck;
            ret.token=token;
            ret.stoken=stoken;
            ret.debugFlag=resData.debugFlag;
            ret.wxNickName=resData.wxNickName;
            if(unionid) {
                ret.unionid=unionid;
            }
            await redis.setHashItem(iconst.wechatCacheMap, ret.uid, JSON.stringify(ret));
            await redis.setHashItem(iconst.wechatCacheMap, ret.account, JSON.stringify(ret));
            //app.wxTokenMap[resData.uid]=ret;
            let offlineData = await this.getUserOfflineData(resData.uid);
            ret.offlineData=offlineData;
            console.logw('get wechat info sucess ',ret);
            //responseSuc=true;
            return ret;
        }else {
            console.logw('createWxUserAsync 434 get_state_info failed . ');
           // responseSuc=true;
            return {code:500,errmsg:"create user failed ."};
        }
        console.logw('createWxUserAsync 444 failed . ');
        return {code:500,errmsg:"unkown err."};
    }

    async getUserOfflineData(uid) {
        let  offlineData='none';
        let historyName=iconst.gameHistoryName;
        let  key='user_'+uid;
        let  roomId=await redis.getHashItem(historyName,key);
        console.logw('getUserOfflineData roomId',key,roomId);
        if(roomId) {
            offlineData = await redis.getHashItem(historyName,roomId);
            console.logw('getUserOfflineData offlineData',offlineData);
            if(!offlineData) offlineData='none';
        }
        return offlineData;
    }

    /**
     * 微信用户登录时保存用户信息
     * @param account
     * @param nickname
     * @param headimgurl
     * @param sex
     * @param ip
     * @param wxNickName
     * @param unionid
     * @returns {Promise<void>}
     */
    async saveWxUserInfo(account,nickname,headimgurl,sex,ip,wxNickName,unionid) {
        let user = {};
        if(unionid && unionid !== undefined){
            user.weixinUid = unionid;
        }else{
            user.account= account;
        }
        user.account=account;
        ///let result = await userDao.getUserByCondition(user);
        let result = await userDao.getUserByAccountOrWeixinUid(user);
        if(result.length>0){
            user = result[0];
        }
        user.account = account;
        user.name = nickname;
        user.wxNickName = nickname;
        user.headimgurl = headimgurl;
        user.sex = sex;
        user.ip = ip;
        user.unionid = unionid;
        user.weixinUid=unionid;
        console.logw(user);
        if(result && result.length>0){
            await userDao.updateWxUser(user);
        }else{
            let result = await userDao.addWxUser(user);
            user.uid = result.uid;
        }
        user.suc = true;
        return user;
    }

    async saveXlUserInfo(account,nickname,headimgurl) {
        let user = {};
        user.account=account;
        ///let result = await userDao.getUserByCondition(user);
        let result = await userDao.getUserByAccountOrXianliaoUid(user);
        if(result.length>0){
            user = result[0];
        }
        user.account = account;
        user.name = nickname;
        user.wxNickName = nickname;
        user.headimgurl = headimgurl;
        console.logw(user);
        if(result && result.length>0){
            await userDao.updateXlUser(user);
        }else{
            let result = await userDao.addXlUser(user);
            user.uid = result.uid;
        }
        user.suc = true;
        return user;
    }


    //add

    /**
     * 
     * @param {String} clubID 
     * @param {Number} mode 
     * @param {String} uid 
     * @param {String} gameType 
     * @param {Number} coins 
     * @param {String} roomID 
     * @param {Number} gameTime 
     */
    async updateCoins(clubID, mode, uid, gameType, coins, roomID, gameTime){
        if(mode === 55){
            console.logw("选择大联盟支付:", clubID, mode,uid, gameType, coins, roomID, gameTime);
            await this.unionCoinsUpdate2(clubID, uid, coins, gameType);
            return;
        }
        console.logw("选择俱乐部支付:", clubID, mode, gameType, coins, roomID, gameTime);
        if(clubID !== "" && mode === 1){
            await this.clubCoinsUpdate(clubID, uid, coins, gameType);
        }else{
            await this.normalCoinsUpdate(roomID, gameType, gameTime, uid, coins);
        }
    }

    async updateUnionCoins(unionID, clubID, mode, uid, gameType, coins, roomID, gameTime){
        await this.unionCoinsUpdate(unionID, clubID, uid, coins, gameType);
    }

    async normalCoinsUpdate(roomID, gameType, gameTime, uid, coins){
        let user = await userDao.getUserInfoByUid(uid);
        if(!user){
            throw new BusiError(500, "更新金币失败, 用户信息不存在");
        }

        console.logw(uid, "当前玩家金币：", user.coinNum, "更新金币：", coins, gameType);
        let res = await userDao.updateCoins(uid, gameType, coins);
        if (res <= 0) {
            throw new BusiError(500, "更新金币失败");
        }

        winLostRecordDao.save(uid, user.name, user.coinNum, coins, gameType, roomID, gameTime);
    }

    /**
     * 
     * @param {String} clubid 
     * @param {String} uid 
     * @param {Number} addCoin 
     * @param {String} gameType 
     */
    async clubCoinsUpdate(clubid, uid, addCoin, gameType){
        let member = await clubMemberDao.getByUID(uid, clubid);
        if(member === null){
            console.logw("俱乐部会员不存在:", clubid, uid, addCoin, gameType);
            throw new BusiError(500, "俱乐部会员不存在");
        }

        let res = await clubMemberDao.upateCoins(uid, clubid, addCoin);
        if(res <= 0){
            console.logw("update club member coins err: res <= 0", uid, clubid, addCoin, gameType);
            throw new BusiError(500, "增加俱乐部成员金币失败");
        }

        let res2 = await clubCoinsUpdateRecordDao.save({club_id:clubid, m_uid:uid, o_uid:member.ownerUid, coins:addCoin, remark:'游戏加减'});
        if(res2 <= 0){
            console.logw("update club member coins err: res <= 0", uid, clubid, addCoin, gameType);
            throw new BusiError(500, "插入俱乐部数据失败");
        }


    }

    //大联盟疲劳值加减
    async unionCoinsUpdate(clubid, uid, addCoin, gameType){
         /*let member = await clubMemberDao.getUnionByUID2(uid, clubid, unionid);
         if(member === null){
            console.logw("大联盟会员不存在:", clubid, uid, addCoin, gameType);
            throw new BusiError(500, "大联盟会员不存在");
         }*/

        let res = await clubMemberDao.upateUnionCoins(uid, clubid, addCoin);
        if(res <= 0){
            console.logw("update club member coins err: res <= 0", uid, clubid, addCoin, gameType);
            throw new BusiError(500, "增加大联盟成员金币失败");
        }

        let res2 = await clubCoinsUpdateRecordDao.save({club_id:clubid, m_uid:uid, o_uid: uid, coins:addCoin, remark:'游戏加减'});
        if(res2 <= 0){
            console.logw("update club member coins err: res <= 0", uid, clubid, addCoin, gameType);
            throw new BusiError(500, "插入大联盟数据失败");
        }
    }

    async unionCoinsUpdate2(clubid, uid, addCoin, gameType){

        let res = await clubMemberDao.upateUnionCoins(uid, clubid, addCoin);
        if(res <= 0){
            console.logw("update club member coins err: res <= 0", uid, clubid, addCoin, gameType);
            throw new BusiError(500, "增加大联盟成员金币失败");
        }

        let res2 = await clubCoinsUpdateRecordDao.save({club_id:clubid, m_uid:uid, o_uid: uid, coins:addCoin, remark:'联盟游戏加减'});
        if(res2 <= 0){
            console.logw("update club member coins err: res <= 0", uid, clubid, addCoin, gameType);
            throw new BusiError(500, "插入大联盟数据失败");
        }
    }

    /**
     * 用户加减金币
     * @param {String} uid
     * @param {Number} addCoin
     * @param {String} type
     * @param {String} remark
     * @param {String} operator
     * @returns {Promise<*>}
     */
    async updateCoin(uid, addCoin, type, remark, operator){
        let user = await userDao.getUserByUid(uid);
        if(!user){
            throw new BusiError(500, "用户不存在, uid:" + uid);
        }

        const limitKey = redisConst.SYS_USER_COIN_UPDATE_LIMIT + ":" + uid;
        let ok = await redis.lock(limitKey, 1, 5);
        if (!ok){
            throw new BusiError(500, "请求太频繁");
        }

        if (user.coinNum + addCoin <= 0){
            throw new BusiError(500, "更新失败, 用户金币更新后小于0");
        }

        // 客服加金币限额
        if(addCoin > 0) {
            let sysUser = await sysUserDao.get(operator);
            if(!sysUser){
                throw new BusiError(500, "非系统用户, 不能加金币");
            }

            if(sysUser.role !== 'admin'){
                const incryKey = redisConst.CUSTOMER_SERVICE_INCRY_COIN_LIMIT + ":" + operator;
                let res = await redis.incrby(incryKey, -addCoin);
                if (res < 0) {
                    await redis.incrby(incryKey, addCoin);
                    throw new BusiError(500, "配置额度不足, 请联系超管增加配额");
                }
            }
        }

        await coinUpdateLogDao.save({uid: uid, coin: Number(addCoin), remark: remark, curCoin: user.coinNum, type: type, operator: operator});

        return await userDao.addCoinSafeAsync(uid, addCoin, type);
    }

    async insertWinRecord(uid, name, totalCoin, addCoin, gameType, d, roomId, gameTime){
        return await userDao.insertWinRecord(uid, name, totalCoin, addCoin, gameType, d, roomId, gameTime);
    }

    async updateUserPassword(uid, newPwd){
        return await userDao.updateUserPassword(uid, newPwd);
    }

    /**
     *
     * @param {String} token
     * @param {String} uid
     * @param {String} ip
     * @param {String} ua
     * @param {String} ch
     * @returns {Promise<void>}
     */
    async loginByTokenOrUUID (token, uid, ip, ua, ch) {
        let debugMode = 0;
        if (uid && uid !== "undefined") {
            console.logw('调试模式', uid);
            debugMode = 1;
        }

        if (debugMode === 0) {
            try {
                let validRes = await tokenService.validToken(token);
                uid = validRes;
            } catch (e) {
                console.logw("token valid failed:", e.message, e);
                throw new BusiError(500, "无效token");
            }
        }

        let version = await redis.getString("version");

        await this.autoIncrCoins(uid);

        let resData = await userDao.getUserByIdAsync(uid);
        if (resData == null) {
            resData = await userDao.getGuestUserByUid(uid);
            if (resData == null) {
                console.logw('无效的请求uid');
                throw new BusiError(500, "无效uid");
            }
        }
        
        if (debugMode === 1 && resData.debugFlag === 0) {
            console.logw('defuse access');
            throw new BusiError(500, "拒绝访问, 请联系管理员");
        }

        userLoginRecordDao.save(uid, ip, ua, ch);

        console.logw('login Res', JSON.stringify(resData));
        let ret = {};
        ret.uid = resData.uid;
        ret.isAgent = resData.isAgent;
        ret.inviteId = resData.inviteId;
        ret.phone = resData.phone;
        ret.phoneCode = resData.phoneCode;
        ret.codeNocheck = resData.codeNocheck;
        ret.cardNum = resData.cardNum;
        ret.headimgurl = resData.headimgurl;
        ret.qrcode = resData.cdnImgurl;
        ret.account = resData.account;
        let cacheToken = await tokenService.getToken(ret.uid);
        if (!cacheToken) {
            cacheToken = await tokenService.updateToken(ret.uid);
        }
        ret.token = cacheToken;
        ret.debugFlag = resData.debugFlag;
        ret.stoken = tokenUtil.aesEncodeDef(ip);
        ret.name = resData.name;

        let sex = parseInt(resData.sex);
        if (sex !== 0 && sex !== 1) {
            sex = 0;
        }
        ret.sex = sex;
        ret.ip = ip;
        ret.phone = resData.phone;
        ret.coinNum = resData.coinNum;
        ret.wxNickName = resData.wxNickName;
        ret.buffer = resData.buffer;
        
        if (!resData.phoneCode) ret.phone = '';
        ret.tick = new Date().getTime();
        let inviteId = 0;
        if (resData.inviteId != null) {
            try {
                let obj = JSON.parse(resData.inviteId);
                inviteId = obj.inviteId;
                console.logw('inviteId', inviteId);
            } catch (e) {
                inviteId = 0;
            }
        }
        let isAgent = resData.isAgent;
        let yes = 0;
        if (isAgent === 1) {
            yes = 1;
        }
        
        if (yes === 1 && inviteId === 0) {
            inviteId = 1;
        }
        
        if (yes === 1 && inviteId === '')
            inviteId = 1;
        ret.inviteId = inviteId;
        ret.code = 200;
        let roomId = await redis.getHashItem(iconst.gameHistoryName, 'user_' + ret.uid);
        ret.roomId = roomId;
        ret.version = version;

        ret.phoneNoCheck = 1;

        if (ret.phoneCode === ret.codeNocheck && ret.phoneCode) {
            ret.phoneNoCheck = 0;
        }
        console.logw('result ', JSON.stringify(ret));

        return ret;
    }

    /**
     * 
     * @param {String} uid 
     * @param {String} agent 
     */
    async addAgentRelationship(uid, agent){
        let user = await userDao.getUserByUid(uid);
        if(!user){
            throw new BusiError(500, "用户不存在, uid:" + uid);
        }

        if(user.code && user.code !== ""){
            throw new BusiError(500, "用户已经存在代理关系, uid:" + uid + ", agent:" + agent);
        }

        let agentUser = await userDao.getUserByUid(agent);
        if(!agentUser){
            throw new BusiError(500, "代理用户不存在, agent:" + agent);
        }

        // todo: 改造， 这里改为MQ通知
        let flag = false;
        for (let i = 0; i < 3; i++) {
            try {
                let result = await cmService.addChild({ acctId: uid, pAcctId: agent});
                if (result) {
                    flag = true;
                    break;
                }
            } catch (e) {
                console.logw("cm service add child failed:", uid, agent, e);
                await timeUtil.timeout((i+1) * 1000);
            }
        }

        if(!flag){
            throw new BusiError(500, "上报代理信息失败");
        }
    }

    async loginByWxCode(){

    }

    /**
     * 用户成为代理
     * @param {String} uid
     * @returns {Promise<void>}
     */
    async toBeAgent(uid){
        let user = await userDao.getUserByUid(uid);

        if(!user){
            throw new BusiError(500, "用户不存在, uid:" + uid);
        }

        if (user.isAgent === 1){
            throw new BusiError(500, "用户已经是代理, uid:" + uid);
        }

        if(user.code && user.code !== ""){
            throw new BusiError(500, "用户已经存在代理关系, uid:" + uid + ", agent:" + user.code);
        }

        let flag = false;
        for (let i = 0; i < 3; i++) {
            try {
                let result = await cmService.addRoot({ acctId: uid});
                if (result) {
                    flag = true;
                    break;
                }
            } catch (e) {
                console.logw("cm service add root failed:", uid, e);
                await timeUtil.timeout((i+1) * 1000);
            }
        }

        if(!flag){
            throw new BusiError(500, "上报代理信息失败");
        }

        await mysqlPool.doWithTx(async (conn)=> {
            let res = await userDao.setUserToAgentWithTx(conn, uid);
            if (res <= 0){
                throw new BusiError(500, "uid:" + uid + "成为代理失败, 请稍后再试!");
            }
        });
    }

    /**
     * 用户创建推广链接
     * @param {String} uid
     * @returns {Promise<String>}
     */
    async getPromoteLink(uid){
        let user = await userDao.getUserByUid(uid);
        if(!user){
            throw new BusiError(500, "用户不存在, uid:" + uid);
        }

        if (user.isAgent !== 1){
            throw new BusiError(500, "用户不是代理, uid:" + uid);
        }

        let uidStr = tokenUtil.aesEncodeDef(uid);
        let baseUrl = apollo.config['promote.url'];
        return baseUrl + "?c=" + uidStr;
    }

    //快3 用户获取战绩
    async getMyK3Record(uid,typePlace,typeAward,page){
        let ret = await userDao.getMyK3Record(uid,typePlace,typeAward,page);
        let retCount = await userDao.getMyK3RecordCount(uid,typePlace,typeAward);

        let cache = {count: retCount, list: ret};
        return cache;
    }
    //推广初始化
    async popularizeK3Init(uid){
        //历史总金额
        let retAll = await userDao.getAdminAllScore(uid);
        //昨日总金额 以及 昨日人数
        let retDay = await userDao.getAdminYDayInfo(uid);
        //可领金额
        let retCan = await userDao.getAdminYCanScore(uid);
        //今天人数
        let retTDay = await userDao.getAdminDCanScore(uid);

        let cache = {all:retAll,yDay:retDay,can:retCan,tDay:retTDay};
        return cache;
    }

    //获取奖励
    async getk3AdminAward(uid){
        let ret = await userDao.getk3AdminAward(uid);
        return ret;
    }

    //推广明细
    async getk3AdminInfo(uid,mType,page){
        //0 1 2 今月 上月 全部
        let ret = await userDao.getk3AdminInfo(uid,mType,page);
        let retCount = await userDao.getk3AdminInfoCount(uid,mType);
        let cache = {count: retCount, list: ret};
        return cache;
    }

    //资金明细
    async getk3ScoreInfo(uid,mType,page){
        let ret = await userDao.getk3ScoreInfo(uid,mType,page);
        let retCount = await userDao.getk3ScoreInfoCount(uid,mType);
        let cache = {count: retCount, list: ret};
        return cache;
    }

    async getMyK3RecordCount(uid,typePlace,typeAward){
        let ret = await userDao.getMyK3RecordCount(uid,typePlace,typeAward);
        return ret;
    }

    /**
     *
     * @param {{uid: String, name: String, phone: String, page: Number}} cond
     * @returns {Promise<{data: Array, cnt: Number}>}
     */
    async getCoinAlterList(cond){
        let cnt = await logCoinNumDao.queryByCondCnt(cond);
        let res = [];
        if (cnt > 0){
            res = await logCoinNumDao.queryByCond(cond);
        }

        return {data: res, cnt: cnt};
    }

    async getUserInfo (uid, ip, ua, ch) {
        let debugMode = 0;
        let version = await redis.getString("version");

       // await this.autoIncrCoins(uid);

        let resData = await userDao.getUserByIdAsync(uid);
        if (resData == null) {
            resData = await userDao.getGuestUserByUid(uid);
            if (resData == null) {
                console.logw('无效的请求uid');
                throw new BusiError(500, "无效uid");
            }
        }

        if (debugMode === 1 && resData.debugFlag === 0) {
            console.logw('defuse access');
            throw new BusiError(500, "拒绝访问, 请联系管理员");
        }

       // userLoginRecordDao.save(uid, ip, ua, ch);

        console.logw('login Res', JSON.stringify(resData));
        let ret = {};
        ret.uid = resData.uid;
        ret.isAgent = resData.isAgent;
        ret.inviteId = resData.inviteId;
        ret.phone = resData.phone;
        ret.phoneCode = resData.phoneCode;
        ret.codeNocheck = resData.codeNocheck;
        ret.cardNum = resData.cardNum;
        ret.headimgurl = resData.headimgurl;
        ret.qrcode = resData.cdnImgurl;
        let cacheToken = await tokenService.getToken(ret.uid);
        if (!cacheToken) {
            cacheToken = await tokenService.updateToken(ret.uid);
        }
        ret.token = cacheToken;
        ret.debugFlag = resData.debugFlag;
        ret.stoken = tokenUtil.aesEncodeDef(ip);
        ret.name = resData.name;

        let sex = resData.sex;
        if (sex !== 0 && sex !== 1) {
            sex = 0;
        }
        ret.sex = sex;
        ret.ip = ip;
        ret.phone = resData.phone;
        ret.coinNum = resData.coinNum;
        ret.wxNickName = resData.wxNickName;
        ret.buffer = resData.buffer;

        if (!resData.phoneCode) ret.phone = '';
        ret.tick = new Date().getTime();
        let inviteId = 0;
        if (resData.inviteId != null) {
            try {
                let obj = JSON.parse(resData.inviteId);
                inviteId = obj.inviteId;
                console.logw('inviteId', inviteId);
            } catch (e) {
                inviteId = 0;
            }
        }
        let isAgent = resData.isAgent;
        let yes = 0;
        if (isAgent === 1) {
            yes = 1;
        }

        if (yes === 1 && inviteId === 0) {
            inviteId = 1;
        }

        if (yes === 1 && inviteId === '')
            inviteId = 1;
        ret.inviteId = inviteId;
        ret.code = 200;
        let roomId = await redis.getHashItem(iconst.gameHistoryName, 'user_' + ret.uid);
        ret.roomId = roomId;
        ret.version = version;

        ret.phoneNoCheck = 1;

        if (ret.phoneCode === ret.codeNocheck && ret.phoneCode) {
            ret.phoneNoCheck = 0;
        }
        console.logw('result ', JSON.stringify(ret));

        return ret;
    }

    async sendFangka (uid, sendUid,cardNum) {
        if(isNaN(Number(cardNum))) {
            throw new BusiError(500, "参数不正确");
        }
        if(Number(cardNum)<0) {
            throw new BusiError(500, "参数不正确");
        }
        let user = await userDao.getUserByUid(sendUid);
        if(user === null){
            throw new BusiError(500, "用户不存在");
        }
        let  ret=await  userDao.sendFangka(uid,sendUid,cardNum)
        return  ret;
    }

    async makeXxCode(uid) {
        var   xxCode=Token.randomStr(16)
        let   key="xxCode:"+xxCode;
        await  redis.setString(key,uid);
        await   redis.setExpire(key,60);//1分钟过期
        return   xxCode;
    }

    async getUidByXxCode(xxCode) {
        var  key="xxCode:"+xxCode;
        var  uid=await redis.getString(key)
        await redis.delString(key);
        return uid;
    }

    async getUserInfoByUid(uid) {
        var   ret=await  userDao.getUserByUid(uid)
        return ret;
    }

}



let userService = new UserService();
module.exports = userService;